<script setup>
import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue'
import { uploadMessageFile } from '@/api/upload'
import VideoComponent from '@/components/VideoComponent.vue'
import { multipartUpload } from '@/utils/upload'
import { useRoute } from 'vue-router'
import {
  HEART_MESSAGE,
  prohibitedWords,
  WS_BASE_URL,
  Base_URL
} from '@/utils/constant.js'
import { useUserStore } from '@/stores/user'
import axiosInstance from '@/utils/request'
import emojiList from '@/utils/emojiList' // 假设你有一个表情包列表文件
import { closeToast, showFailToast } from 'vant'
import router from '@/router'
import { showImagePreview } from 'vant'
const store = useUserStore()
const route = useRoute()
const emojiPanelVisible = ref(false) // 表情包面板是否显示
// 获取用户id
const userId = store.user.id
// 获取联系人信息
const contactId = route.query.contactId
// 获取联系人名称
const contactName = route.query.contactName
// 获取用户头像
const userAvatar = store.user.avatar
// 获取联系人头像
const contactAvatar = route.query.avatar
const inputMessage = ref('')
// 获取联系人类型
const contactType = Number(route.query.contactType)

console.log('contactType', contactType)
// 获取会话Id
// const sessionId = ref(null)
const messages = ref([])
const ws = ref(null)
const messageListRef = ref(null)
const emojiPanel = ref(null) // 表情面板的ref
const fileInput = ref(null)
const aiStreamingMsg = ref({
  content: '', // 实时拼接的流式内容
  isStreaming: false // 是否正在流式输出
})
const sendAiMsg = () => {
  // 构建参数
  const params = {
    fromUserId: userId,
    toUserId: contactId,
    content: inputMessage.value
  }

  // 构建带参数的URL
  const queryParams = new URLSearchParams(params).toString()
  const url = `${Base_URL}/message/sendToAi?${queryParams}`

  messages.value.push({
    senderId: userId,
    messageType: 0,
    content: inputMessage.value,
    isSelf: true,
    ack: 0
  })

  aiStreamingMsg.value = {
    content: '',
    isStreaming: true
  }

  messages.value.push({
    senderId: contactId,
    messageType: 0,
    content: aiStreamingMsg.value.content,
    isSelf: false,
    ack: 0,
    isStreaming: true // 标记用于样式区分
  })
  scrollToBottom()

  // 创建EventSource实例
  const eventSource = new EventSource(url)

  // 监听增量内容事件
  eventSource.addEventListener('delta', (event) => {
    const delta = event.data
    console.log(delta)
    aiStreamingMsg.value.content += delta
    // 更新 messages 中最后一条（AI 回复）的内容
    messages.value[messages.value.length - 1].content =
      aiStreamingMsg.value.content
    scrollToBottom()
  })

  // 监听完成事件
  eventSource.addEventListener('complete', (event) => {
    aiStreamingMsg.value.isStreaming = false
    // 标记 AI 回复已完成
    messages.value[messages.value.length - 1].isStreaming = false
    scrollToBottom()
    eventSource.close()
  })

  // 监听错误事件
  eventSource.onerror = (event) => {
    console.error('SSE连接错误:', event)
    aiStreamingMsg.value.content = '连接出错，请重试'
    aiStreamingMsg.value.isStreaming = false
    messages.value[messages.value.length - 1].isStreaming = false
    messages.value[messages.value.length - 1].content = aiStreamingMsg.value.content
    eventSource.close()
    scrollToBottom()
  }

  // 返回关闭连接的函数
  return () => eventSource.close()
}

// 获取历史消息
const getHistoryMessage = () => {
  axiosInstance
    .get('/message/list', {
      params: {
        contactId: contactId
      }
    })
    .then((response) => {
      messages.value = response.data.data
      scrollToBottom()
    })
    .catch((error) => {
      console.log(error)
    })
}
const connectWebSocket = () => {
  ws.value = new WebSocket(WS_BASE_URL + `/ws?token=${store.token}`)

  ws.value.onopen = () => {
    console.log('WebSocket连接已建立......')
  }

  ws.value.onmessage = (event) => {
    if (event.data === HEART_MESSAGE) {
      // 忽略心跳消息
      console.warn('接收到心跳消息......')
      return
    }
    
    const message = JSON.parse(event.data)
    console.log('接收到消息', message)

    if (message.type === 'sendToUser') {
      if (message.content.sessionId == route.query.sessionId) {
        messages.value.push(message.content)
        // 回传 ACK
        ws.value.send(
          JSON.stringify({
            type: 'ack',
            msgId: message.content.id,
            sessionId: message.content.sessionId,
            contactId: contactId
          })
        )
        scrollToBottom()
      }
    } else if (message.type === 'ack') {
      console.log('进入ack')
      console.log(message.content)
      if (
        message.content &&
        Array.isArray(message.content) &&
        message.content[0]
      ) {
        if (message.content[0].sessionId == route.query.sessionId) {
          const msgContents = message.content
          msgContents.forEach((element) => {
            const pos = messages.value.findIndex((msg) => msg.id === element.id)
            if (pos !== -1) {
              messages.value[pos].ack = 1 // 更新已读状态
            }
          })
        }
      }
    }
  }

  ws.value.onclose = () => {
    console.log('WebSocket连接已关闭......')
  }

  ws.value.onerror = (error) => {
    console.error('WebSocket错误:', error)
  }
}

const sendMessage = () => {
  if (inputMessage.value.trim() === '') {
    showToast('消息不能为空')
    return
  }
  const isProhibit = containsProhibitedWords(inputMessage.value)
  if (isProhibit) {
    showFailToast('文本中包含违禁词')
    return
  }

  // 文本发送
  if (contactType === 1) {
    console.log(contactType)
    sendMsg(0, 1)
  } else if (contactType === 2) {
    sendAiMsg()
  }
  inputMessage.value = '' // 清空输入框
}

const sendMsg = (type, contactType) => {
  axiosInstance
    .post(
      '/message/send',
      {
        fromUserId: userId,
        toUserId: contactId,
        content: inputMessage.value,
        type: type,
        contactType: contactType
      },
      {
        timeout: 50000 // 设置超时时间为 50 秒（50000 毫秒）
      }
    )
    .then((response) => {
      if (response.data.data) {
        showFailToast(response.data.data)
      }
    })
    .catch((error) => {
      console.log(error)
    })
}

const scrollToBottom = () => {
  nextTick(() => {
    if (messageListRef.value) {
      messageListRef.value.scrollTo({
        top: messageListRef.value.scrollHeight,
        behavior: 'smooth' // 平滑滚动
      })
    }
  })
}
const handleClickOutside = (e) => {
  if (emojiPanel.value && !emojiPanel.value.contains(e.target)) {
    emojiPanelVisible.value = false // 点击外部时关闭表情面板
    console.log('handleClickOutside', emojiPanelVisible.value)
  }
}

const toggleFilePanel = () => {
  fileInput.value.click()
}

const handleFileChange = (e) => {
  console.log('文件选择事件:', e)
  const file = e.target.files[0]
  if (!file) return
  // 1. 检查文件类型和大小
  const allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'video/mp4']
  if (!allowedTypes.includes(file.type)) {
    showFailToast('不支持的文件类型，请上传图片或视频')
    return
  }
  // 限制文件大小（这里设置为10MB）
  const maxSize = 80 * 1024 * 1024 // 100MB
  if (file.size > maxSize) {
    showFailToast('文件过大,最大支持10MB')
    return
  }
  if (file.type === 'video/mp4') {
    uploadToServer(file, 'video')
  } else {
    uploadToServer(file)
  }
}

const uploadToServer = async (file, bucket) => {
  try {
    let response = null
    // 显示上传中提示
    showLoadingToast('发送中...')
    // 调用API上传文件
    if (bucket === 'video') {
      response = await multipartUpload(file)
    } else {
      response = await uploadMessageFile({
        file
      })
    }
    // 隐藏加载提示
    closeToast()
    console.log('文件上传成功:', response)
    if (bucket === 'video') {
      // 如果是视频文件，直接发送视频消息
      sendFileMessage(response.data.fileUrl, 2)
    } else {
      sendFileMessage(response.fileUrl, 1)
    }
  } catch (error) {
    // 隐藏加载提示
    closeToast()
    // 处理错误
    if (error.response) {
      // 服务器返回错误状态码
      console.error('服务器错误:', error.response.data)
    } else {
      // 网络错误或其他问题
      console.error('网络错误:', error.message)
    }

    throw error // 继续抛出错误，让调用者知道上传失败
  }
}

const sendFileMessage = (fileUrl, type) => {
  // 发送图片消息逻辑
  inputMessage.value = fileUrl
  sendMsg(type)
  inputMessage.value = ''
}

const handleImageDetail = (imageUrl) => {
  showImagePreview([imageUrl])
}

onMounted(() => {
  // 建立 WebSocket 连接
  connectWebSocket()
  // 调用获取历史消息
  getHistoryMessage()
  // 监听全局点击
  document.addEventListener('click', handleClickOutside)
})

onBeforeUnmount(() => {
  if (ws.value) {
    ws.value.close() // 组件卸载时关闭连接
  }
  // 移除监听
  document.removeEventListener('click', handleClickOutside)
})
const onClickLeft = () => history.back()

const toggleEmojiPanel = () => {
  emojiPanelVisible.value = !emojiPanelVisible.value
  console.log('emojiPanelVisible', emojiPanelVisible.value)
}

const insertEmoji = (emoji) => {
  console.log(emoji)
  inputMessage.value += emoji
  emojiPanelVisible.value = false
}

const handleUserDetail = () => {
  router.push(`/contact/${contactId}`)
}

function containsProhibitedWords(inputText) {
  // 遍历违禁词列表
  for (let word of prohibitedWords) {
    // 将正则中的特殊字符转义
    const regex = new RegExp(word, 'i') // 'i' 代表不区分大小写
    if (regex.test(inputText)) {
      return true // 如果匹配到违禁词，返回true
    }
  }
  return false // 没有违禁词，返回false
}
</script>

<template>
  <div class="chat-container">
    <van-nav-bar
      :title="contactName"
      left-text="返回"
      left-arrow
      @click-left="onClickLeft"
    />
    <div class="message-list" ref="messageListRef">
      <div
        v-for="(message, index) in messages"
        :key="index"
        class="message"
        :class="{
          'my-message': message.senderId === userId,
          'other-message': message.senderId !== userId
        }"
      >
        <img
          class="avatar"
          @click="handleUserDetail"
          :src="message.senderId === userId ? userAvatar : contactAvatar"
          alt="头像"
        />
        <div v-if="message.messageType === 0" class="bubble">
          <template v-if="message.isStreaming && message.senderId !== userId">
            {{ message.content }}
            <van-loading size="12" class="typing-indicator" />
          </template>
          <!-- 普通消息 -->
          <template v-else>
            {{ message.content }}
          </template>
        </div>
        <div v-else-if="message.messageType === 1">
          <img
            @click="handleImageDetail(message.content)"
            :class="
              message.senderId === userId ? 'message-img' : 'contactMessage-img'
            "
            :src="message.content"
            alt="文件"
          />
        </div>
        <div v-else-if="message.messageType === 2" class="video-wrap">
          <VideoComponent :videoSrc="message.content" />
        </div>
        <span
          v-if="message.ack === 1 && message.senderId === userId"
          class="read-indicator"
          >已读</span
        >
      </div>
    </div>
    <div class="input-container">
      <input
        v-model="inputMessage"
        @keyup.enter="sendMessage"
        placeholder="发送消息"
        class="input-message"
      />
      <button @click="sendMessage" class="send-button">发送</button>
    </div>
    <div>
      <button class="emoji-button" @click="toggleEmojiPanel" ref="emojiPanel">
        <span class="emoji-icon">😀</span>
      </button>
      <button
        v-if="contactType === 1"
        class="file-button"
        @click="toggleFilePanel"
      >
        <span style="color: gray"><van-icon name="photo" /></span>
      </button>
      <div v-if="emojiPanelVisible" class="emoji-panel">
        <span
          v-for="(emoji, index) in emojiList"
          :key="index"
          class="emoji"
          @click="insertEmoji(emoji)"
        >
          {{ emoji }}
        </span>
      </div>
    </div>
  </div>
  <!-- 隐藏的文件输入框 -->
  <input
    ref="fileInput"
    type="file"
    accept="image/*,video/*"
    class="hidden"
    @change="handleFileChange"
  />
</template>
<style scoped>
.chat-container {
  width: 100%;
  height: 100vh; /* 让聊天框充满整个视口 */
  display: flex;
  flex-direction: column;
  background-color: #f9f9f9;
  padding-bottom: 0; /* 去掉底部边距 */
}
.typing-indicator {
  display: inline-block;
  margin-left: 4px;
}

.message-list {
  flex: 1;
  overflow-y: auto;
  padding: 10px;
  border-bottom: 1px solid #ccc;
}

.message {
  display: flex;
  align-items: flex-end; /* 垂直对齐 */
  margin-bottom: 10px;
}

.message .bubble {
  color: #232323;
}

.avatar {
  width: 35px; /* 头像大小 */
  height: 35px;
  border-radius: 50%; /* 圆形头像 */
}

.bubble {
  position: relative;
  max-width: 60%; /* 气泡最大宽度 */
  padding: 5px;
  background-color: #eaeaea; /* 气泡背景色（绿色） */
  word-wrap: break-word; /* 自动换行 */
}

.bubble::after {
  content: '';
  position: absolute;
  bottom: 100%; /* 顶部对齐 */
  left: 100%; /* 调整三角形水平位置 */
  border-width: 8px 6px 0; /* 三角形的高度和宽度 */
  border-style: solid;
  border-color: #95ec69 transparent transparent transparent; /* 颜色与气泡一致 */
}

.my-message {
  flex-direction: row-reverse; /* 自己的消息在右侧 */
}

.my-message .bubble {
  position: relative;
  max-width: 60%;
  padding: 5px;
  margin-right: 4px;
  background-color: #95ec69;
  word-wrap: break-word;
}

.my-message .bubble::after {
  content: '';
  position: absolute;
  top: 50%; /* 垂直居中三角形 */
  right: -8px; /* 将三角形移到气泡的右侧，间距为 8px */
  border-width: 6px 8px 6px 0; /* 三角形的高度和宽度 */
  border-style: solid;
  border-color: #95ec69 transparent transparent transparent; /* 三角形的颜色与气泡一致 */
  transform: translateY(-50%); /* 垂直居中三角形 */
}

.message-img {
  max-width: 150px; /* 最大宽度 */
  max-height: 150px; /* 最大高度 */
  width: auto;
  height: auto;
  margin-right: 10px;
  border-radius: 8px;
  object-fit: contain; /* 保持比例，不拉伸 */
}

.contactMessage-img {
  max-width: 150px; /* 最大宽度 */
  max-height: 150px; /* 最大高度 */
  width: auto;
  height: auto;
  margin-left: 10px;
  border-radius: 8px;
  object-fit: contain; /* 保持比例，不拉伸 */
}

.other-message .bubble {
  position: relative;
  max-width: 60%;
  margin-left: 13px;
  padding: 5px;
  background-color: #e0e0e0;
  word-wrap: break-word;
}

.other-message .bubble::after {
  content: '';
  position: absolute;
  bottom: 50%; /* 调整箭头的垂直位置 */
  left: -8px; /* 将箭头位置调整到气泡的左侧 */
  border-width: 4px 8px 2px 0;
  border-style: solid;
  border-color: transparent #e0e0e0 transparent transparent; /* 设置箭头颜色 */
}

/* 修改已读状态的显示 */
.read-indicator {
  font-size: 10px; /* 字体大小变小 */
  color: green; /* 文字颜色为灰色 */
  margin-left: 8px; /* 左边距，避免与消息内容挤在一起 */
  align-self: flex-end; /* 垂直居中 */
  padding-right: 3px;
}

.input-container {
  display: flex;
  align-items: center;
  background-color: #fff;
  /* box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); */
}

.input-message {
  flex: 1;
  padding: 6px 12px;
  border: 1px solid #ccc;
  border-radius: 20px;
  color: #232323;
  font-size: 14px; /* 设置输入框中文本的大小 */
  margin-right: 10px;
}

.send-button {
  padding: 6px 12px;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 20px;
  cursor: pointer;
  font-size: 14px; /* 设置发送按钮的字体大小 */
}

input {
  flex: 1;
  padding: 8px;
  border: 1px solid #ccc;
  border-radius: 20px; /* 圆角 */
  margin-right: 10px; /* 输入框与按钮的间隔 */
}

.emoji-button {
  padding: 8px 12px;
  color: white;
  background-color: #fff;
  border: none;
  border-radius: 20px; /* 圆角 */
  cursor: pointer;
}

.file-button {
  background-color: #fff;
  border: none;
}

.emoji-panel {
  position: absolute;
  bottom: 60px; /* 调整位置 */
  left: 10px;
  background-color: white;
  border: 1px solid #ccc;
  border-radius: 10px;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
  padding: 10px;
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  max-width: 300px;
}

.video-wrap {
  width: 70%;
  max-width: 300px; /* 限制视频宽度，避免过大 */
  border-radius: 8px; /* 圆角，与消息风格统一 */
  overflow: hidden; /* 隐藏溢出内容 */
  margin: 5px 5px 0 5px; /* 上右下左边距 */
}

/* 覆盖 VideoPlayer 内部样式 */
.video-wrap >>> .video-js {
  width: 100%;
  height: auto;
  background-color: #000; /* 视频背景为黑色，提升对比度 */
}

.video-wrap >>> .vjs-control-bar {
  background-color: rgba(0, 0, 0, 0.7); /* 半透明控件栏，增强可见性 */
  color: white; /* 控件颜色为白色 */
}

.hidden {
  display: none;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .chat-container {
    padding: 0 10px; /* 小屏幕边距 */
  }
}
</style>
